package com.wb3.meta.common.utils;


import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.common.utils.BinaryUtil;
import com.aliyun.oss.model.MatchMode;
import com.aliyun.oss.model.PolicyConditions;
import com.wb3.meta.common.pojo.ResultT;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;

/**
 * 上传文件工具类
 *
 * @param
 * @author ron
 * @date 2020/12/14 22:50
 * @return
 */
@Slf4j
@Configuration
public class UploadFileUtils {

    @Value("${aliyun.secretId}")
    private String secretId;
    @Value("${aliyun.secretKey}")
    private String secretKey;
    @Value("${aliyun.endPoint}")
    private String endPoint;
    @Value("${aliyun.bucketName}")
    private String bucketName;

    /**
     * 上传文件方法
     *
     * @return java.util.Map<java.lang.String, java.lang.Object>
     * @author ron
     * @date 2020/12/14 22:50
     */
    public ResultT uploadFileToAliyun(String dir, String fileName, MultipartFile files) {
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endPoint, secretId, secretKey);
        // 上传文件流。
        try {
            log.info("上传文件{}到{}，开始---", fileName, dir);
            // 判断图片的格式是否符合要求
//            String fName = files.getOriginalFilename(); // 上传的文件名
//            String suffix = fName.substring(fName.lastIndexOf(".") + 1).toLowerCase();
//            if (!"jpg".equals(suffix) && !"jpeg".equals(suffix) && !"png".equals(suffix)) {
//                return ResultT.fail(0, "请确认上传文件为图片格式", fileName);
//            } else if (files.getSize() > 2097152) {
//                return ResultT.fail(0, "图片超过2MB，请裁剪后重新上传", fileName);
//            } else {
            InputStream inputStream = files.getInputStream();
            ossClient.putObject(bucketName, dir +"/"+ fileName, inputStream);
            fileName = String.format("https://%s.%s/%s", bucketName, endPoint, dir +"/"+ fileName);

            // 关闭OSSClient。
            ossClient.shutdown();
//            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("文件：{}，上传阿里云oss失败，错误原因：{}", fileName, e.getMessage());
            return ResultT.fail(0, "上传失败，请重试", fileName);
        }
        return ResultT.success("Upload success", fileName);
    }


    public ResultT ossPolicy(String prefix) throws UnsupportedEncodingException {
        String host = String.format("https://%s.%s", bucketName, endPoint);
        long expireTime = 3000;
        long expireEndTime = System.currentTimeMillis() + expireTime * 1000;
        Date expiration = new Date(expireEndTime);
        PolicyConditions policyCond = new PolicyConditions();
        // 最大支持10g
        policyCond.addConditionItem(PolicyConditions.COND_CONTENT_LENGTH_RANGE, 0, 10737418240L);
        policyCond.addConditionItem(MatchMode.StartWith, PolicyConditions.COND_KEY, prefix);
        OSS ossClient = new OSSClientBuilder().build(endPoint, secretId, secretKey);
        String postPolicy = ossClient.generatePostPolicy(expiration, policyCond);
        byte[] binaryData = postPolicy.getBytes("utf-8");
        String encodedPolicy = BinaryUtil.toBase64String(binaryData);
        String postSignature = ossClient.calculatePostSignature(postPolicy);

        Map<String, Object> resultMap = new HashMap<>(6, 1);
        resultMap.put("accessId", secretId);
        resultMap.put("policy", encodedPolicy);
        resultMap.put("signature", postSignature);
        resultMap.put("dir", prefix);
        resultMap.put("host", host);
        resultMap.put("expire", expireEndTime / 1000);
        return ResultT.success("Upload success", resultMap);
    }


    public ResultT uploadFileToAliyun(String dir, String fileName, File file) {
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endPoint, secretId, secretKey);
        // 上传文件流。
        try {
            log.info("上传文件{}到{}，开始---", fileName, dir);
            // 判断图片的格式是否符合要求
            ossClient.putObject(bucketName, dir +"/"+ fileName, file);
            fileName = String.format("https://%s.%s/%s", bucketName, endPoint, dir +"/"+ fileName);
            // 关闭OSSClient。
            ossClient.shutdown();
        } catch (Exception e) {
            e.printStackTrace();
            log.error("文件：{}，上传阿里云oss失败，错误原因：{}", fileName, e.getMessage());
            return ResultT.fail(0, "上传失败，请重试", fileName);
        }
        return ResultT.success("Upload success", fileName);
    }

    public ResultT uploadFileToAliyun(String dir, String fileName, String path) {
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endPoint, secretId, secretKey);
        log.info("上传文件{}到{}，开始---", fileName, dir);

        File file = new File(path);
        if (!file.exists()) {
            // 关闭OSSClient。
            ossClient.shutdown();
            log.error("文件：{}，上传阿里云oss失败，错误原因：{}", fileName, path + "不存在！");
            return ResultT.fail(0, "上传失败，请重试", fileName);
        }
        if (file.isDirectory()) {
            // 上传文件流。
            try (Stream<Path> paths = Files.walk(Paths.get(path), 2)) {
                paths.filter(Files::isRegularFile).forEach(f -> {
                    ossClient.putObject(bucketName, dir + "/" + fileName, file);
                });
            } catch (Exception e) {
                // 关闭OSSClient。
                ossClient.shutdown();
                e.printStackTrace();
                log.error("文件：{}，上传阿里云oss失败，错误原因：{}", fileName, e.getMessage());
                return ResultT.fail(0, "上传失败，请重试", fileName);
            }
            // 关闭OSSClient。
            ossClient.shutdown();
        }
        return ResultT.success("Upload success", fileName);
    }

    public ResultT uploadFileToAliyun(String dir, String fileName, InputStream file) {
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endPoint, secretId, secretKey);
        // 上传文件流。
        try {
            log.info("上传文件{}到{}，开始---", fileName, dir);
            // 判断图片的格式是否符合要求
            ossClient.putObject(bucketName, dir + fileName, file);
            fileName = String.format("https://%s.%s/%s", bucketName, endPoint, dir + fileName);
            // 关闭OSSClient。
            ossClient.shutdown();
        } catch (Exception e) {
            e.printStackTrace();
            log.error("文件：{}，上传阿里云oss失败，错误原因：{}", fileName, e.getMessage());
            return ResultT.fail(0, "上传失败，请重试", fileName);
        }
        return ResultT.success("Upload success", fileName);
    }
    /**
     * @param fileKey 上传之后返回的文件key
     * @return com.wb3.meta.common.pojo.ResultT
     * @Description //通用删除上传文件方法
     * @Date 2022/6/20 11:05
     * @Param [vo]
     */
    public ResultT delUploadFileToAliyun(String fileKey){
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endPoint, secretId, secretKey);
        // 上传文件流。
        try {
            log.info("删除文件{}，开始---", fileKey);
            ossClient.deleteObject(bucketName, fileKey);
            // 关闭OSSClient。
            ossClient.shutdown();
//            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error("文件：{}，删除阿里云oss失败，错误原因：{}", fileKey, e.getMessage());
            return ResultT.fail(0, "删除失败，请重试", fileKey);
        }
        return ResultT.success("删除成功", fileKey);
    }

    /**
     * @param fileKey 上传之后返回的文件key
     * @return com.wb3.meta.common.pojo.ResultT
     * @Description //通用分享上传文件方法
     * @Date 2022/6/20 11:05
     * @Param [vo]
     */
    public ResultT shareUploadFileToAliyun(String fileKey){
        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endPoint, secretId, secretKey);
        // 上传文件流。
        try {
            // 设置签名URL过期时间，单位为毫秒。
            Date expiration = new Date(new Date().getTime() + 3600 * 1000);
            // 生成以GET方法访问的签名URL，访客可以直接通过浏览器访问相关内容。
            URL url = ossClient.generatePresignedUrl(bucketName, fileKey, expiration);
            System.out.println(url);
        } catch (OSSException oe) {
            log.error("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            log.error("Error Message:{}，Error Code:{}, Request ID::{}, Host ID:" , oe.getErrorMessage(), oe.getErrorCode(),  oe.getRequestId(),  oe.getHostId());
        } catch (ClientException ce) {
            log.error("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            log.error("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
        return ResultT.success("分享成功", fileKey);
    }


    /**
     * @Author raopeng
     * @Description //TODO 图片链接转存到阿里云oss
     * @Date 2022/7/11 11:07
     * @Param [imgUrl]
     * @return java.lang.String
     **/
    public String imgUploadAliyun(String fileDir,String imgUrl) {

        String filename = System.currentTimeMillis() + ".jpg";
        File imgFile = HttpUtils.urlToFile(imgUrl);
        String newFile = uploadFileToAliyun(fileDir, filename, imgFile).getData().toString();
        log.debug("原图地址：{}，生成新的图：{}",imgUrl, newFile);
        return newFile;
    }

}
